package com.mini.service;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mini.client.AssignClient;
import com.mini.client.WehubSocketReceiverClient;
import com.mini.conditon.BusinessConditionNew;
import com.mini.conditon.ChanceBaseInfoCondition;
import com.mini.conditon.ChanceTimeCondition;
import com.mini.conditon.TraditionChanceCondition;
import com.mini.config.BusinessException;
import com.mini.constant.ChanceFollowEventType;
import com.mini.model.*;
import com.mini.repository.*;
import com.mini.util.BeanPropertiesUtil;
import com.mini.util.CalendarUtil;
import com.mini.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.persistence.criteria.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.mini.config.RedisConfig.CacheKeys.item_info_all_list;
import static java.util.Calendar.DATE;

/**
 * @author shixiaopeng  on 2020/12/2
 */
@Service
@Slf4j
public class BusinessTraditionChanceService extends BaseService implements BeanPropertiesUtil {
    @Autowired
    private BusinessTraditionChanceRepository businessTraditionChanceRepository;

    @Autowired
    private BusinessChanceWechatRepository businessChanceWechatRepository;

    @Autowired
    private BusinessChancePhoneRepository businessChancePhoneRepository;

    @Autowired
    private BusinessChancePhoneRecordRepository businessChancePhoneRecordRepository;
    @Autowired
    private BusinessChanceWechatRecordRepository businessChanceWechatRecordRepository;

    @Autowired
    private BusinessChanceConvertRecordRepository businessChanceConvertRecordRepository;

    @Autowired
    private BusinessItemInfoRepository businessItemInfoRepository;
    @Autowired
    private BusinessBaseInfoRepository businessBaseInfoRepository;

    @Autowired
    private BusinessWechatOperateRecordRepository businessWechatOperateRecordRepository;

    @Autowired
    private BusinessChanceCallRecordRepository businessChanceCallRecordRepository;

    @Autowired
    private BusinessBaseService businessBaseService;

    @Autowired
    private SendMsg2RabbitMQService sendMsg2RabbitMQService;

    @Autowired
    private MiniAdminService miniAdminService;

    @Autowired
    private WehubSocketReceiverClient wehubSocketReceiverClient;

    @Autowired
    private AssignClient assignClient;


    @Cacheable(cacheNames = item_info_all_list, key = "all", unless = "#result == null")
    public List<BusinessItemInfo> getAllItemInfo() {
        return businessItemInfoRepository.findAllByItemState(BusinessItemInfo.StateEnum.valid.code);
    }

    public Page<BusinessTraditionChance> searchHandle(TraditionChanceCondition condition){
        List<Long> siteIds = new ArrayList<>();
        //根据投放人员id和渠道id，查询站点id---跃飞提供
        BusinessConditionNew conditionFindSiteIds = new BusinessConditionNew();
        Long launchManId = condition.getLaunchManId();
        Integer channelId = condition.getChannelId();
        if (Objects.nonNull(launchManId) || Objects.nonNull(channelId)) {
            conditionFindSiteIds.setFzId(launchManId);
            conditionFindSiteIds.setChannelId(channelId);
            List<BusinessBaseInfo> baseInfos = businessBaseService.getAllByCondition(conditionFindSiteIds);

            siteIds = baseInfos.stream().map(businessBaseInfo -> businessBaseInfo.getMiniLessonId()).collect(Collectors.toList());
            log.info("查询出来的站点id集合:{}", siteIds);
            if (CollectionUtils.isEmpty(siteIds)) {
                return new PageImpl(Collections.EMPTY_LIST);
            }
        }
        if (conditionHandle(condition)){
            return new PageImpl(Collections.EMPTY_LIST);
        }
        List<Long> finalSiteIds = siteIds;
        Specification<BusinessTraditionChance> specification = getBusinessTraditionChanceSpecification(condition, finalSiteIds);
        Sort sort = new Sort(Sort.Direction.fromString(condition.getSortType()), Lists.newArrayList(condition.getSortColumn()));
        Pageable pageable = buildPageRequest(condition.getPageNumber(), condition.getPageSize(), sort);
        log.info("pageable {}",pageable);
        return businessTraditionChanceRepository.findAll(specification, pageable);
    }


    public PageResultVO<BusinessTraditionChanceVO> search(TraditionChanceCondition condition) {
        StopWatch stopWatch = new StopWatch("tradition-page");

        stopWatch.start("tradition-one");
        List<Long> siteIds = new ArrayList<>();
        //根据投放人员id和渠道id，查询站点id---跃飞提供
        BusinessConditionNew conditionFindSiteIds = new BusinessConditionNew();
        Long launchManId = condition.getLaunchManId();
        Integer channelId = condition.getChannelId();
        if (Objects.nonNull(launchManId) || Objects.nonNull(channelId)) {
            conditionFindSiteIds.setFzId(launchManId);
            conditionFindSiteIds.setChannelId(channelId);
            List<BusinessBaseInfo> baseInfos = businessBaseService.getAllByCondition(conditionFindSiteIds);

            siteIds = baseInfos.stream().map(businessBaseInfo -> businessBaseInfo.getMiniLessonId()).collect(Collectors.toList());
            log.info("查询出来的站点id集合:{}", siteIds);
            if (CollectionUtils.isEmpty(siteIds)) {
                return getBusinessTraditionChanceVOPageResultVO();
            }
        }
        if (conditionHandle(condition)){
            return getBusinessTraditionChanceVOPageResultVO();
        }
        List<Long> finalSiteIds = siteIds;
        Specification<BusinessTraditionChance> specification = getBusinessTraditionChanceSpecification(condition, finalSiteIds);
        Sort sort = new Sort(Sort.Direction.fromString(condition.getSortType()), Lists.newArrayList(condition.getSortColumn()));
        Pageable pageable = buildPageRequest(condition.getPageNumber(), condition.getPageSize(), sort);
        log.info("pageable {}",pageable);
        stopWatch.stop();
        stopWatch.start("tradition-two");
        Page<BusinessTraditionChance> businessTraditionChancesPage = businessTraditionChanceRepository.findAll(specification, pageable);
        List<BusinessTraditionChance> traditionChances = businessTraditionChancesPage.getContent();
        stopWatch.stop();
        return getBusinessTraditionChanceVOPageResultVO(stopWatch, businessTraditionChancesPage, traditionChances, condition.getToken());
    }

    private boolean conditionHandle(TraditionChanceCondition condition) {
        //未分配，机会时间不能包含今天
        if(Objects.nonNull(condition.getChanceStatus()) && condition.getChanceStatus().intValue() == ChanceBaseInfoVO.ChanceStatus.nodistribute.code.intValue()){
            String dateStr = CalendarUtil.getShortDateString(new Date());
            Date today = CalendarUtil.parseShortDate(dateStr);
            String yesterday = CalendarUtil.getBeforDay();
            List<ChanceTimeCondition> chanceTimes = condition.getChanceTimes();

            //是否包含创建时间参数
            final boolean[] isContainCreate = {false};
            if (CollectionUtils.isNotEmpty(chanceTimes)) {
                //时间只包含当日
                final boolean[] isCreateValide = {false};
                chanceTimes.forEach(chanceTimeCondition -> {
                    int typeValue = chanceTimeCondition.getType().intValue();
                    if (typeValue == TraditionChanceCondition.ChanceTimeEnum.create.code) {
                        isContainCreate[0] = true;
                        Date beginTime = CalendarUtil.parseShortDate(chanceTimeCondition.getBeginTime());
                        Date endTime = CalendarUtil.parseShortDate(chanceTimeCondition.getEndTime());
                        if(today.compareTo(beginTime) ==0 && today.compareTo(endTime) == 0){
                            isCreateValide[0] = true;
                        }else{
                            chanceTimeCondition.setEndTime(yesterday);
                        }
                    }
                });
                if(isCreateValide[0]){
                    return true;
                }
            }
            if(!isContainCreate[0]){
                if(Objects.isNull(chanceTimes)){
                    chanceTimes = new ArrayList<>();
                    condition.setChanceTimes(chanceTimes);
                }
                ChanceTimeCondition createTimeCondition = new ChanceTimeCondition();
                createTimeCondition.setType(TraditionChanceCondition.ChanceTimeEnum.create.code);
                createTimeCondition.setEndTime(yesterday);
                chanceTimes.add(createTimeCondition);
            }
        }
        //增加分配中的状态查询
        if(Objects.nonNull(condition.getChanceStatus()) && condition.getChanceStatus().intValue() == ChanceBaseInfoVO.ChanceStatus.distributing.code.intValue()){
            condition.setChanceStatus(ChanceBaseInfoVO.ChanceStatus.nodistribute.code);

            String dateStr = CalendarUtil.getShortDateString(new Date());
            List<ChanceTimeCondition> chanceTimes = condition.getChanceTimes();

            //是否包含创建时间参数
            final boolean[] isContainCreate = {false};
            if (CollectionUtils.isNotEmpty(chanceTimes)) {
                //时间不包含当日
                final boolean[] isCreateValide = {false};
                chanceTimes.forEach(chanceTimeCondition -> {
                    int typeValue = chanceTimeCondition.getType().intValue();
                    if (typeValue == TraditionChanceCondition.ChanceTimeEnum.create.code) {
                        isContainCreate[0] = true;
                        Date beginTime = CalendarUtil.parseShortDate(chanceTimeCondition.getBeginTime());
                        Date endTime = CalendarUtil.parseShortDate(chanceTimeCondition.getEndTime());

                        Date today = CalendarUtil.parseShortDate(dateStr);
                        if(today.compareTo(beginTime) >=0 && today.compareTo(endTime) <= 0){
                            chanceTimeCondition.setBeginTime(dateStr);
                            chanceTimeCondition.setEndTime(dateStr);
                        }else{
                            isCreateValide[0] = true;
                        }
                    }
                });
                if(isCreateValide[0]){
                    return true;
                }
            }
            if(!isContainCreate[0]){
                if(Objects.isNull(chanceTimes)){
                    chanceTimes = new ArrayList<>();
                    condition.setChanceTimes(chanceTimes);
                }
                ChanceTimeCondition createTimeCondition = new ChanceTimeCondition();
                createTimeCondition.setType(TraditionChanceCondition.ChanceTimeEnum.create.code);
                createTimeCondition.setBeginTime(dateStr);
                createTimeCondition.setEndTime(dateStr);
                chanceTimes.add(createTimeCondition);
            }
        }
        return false;
    }

    private PageResultVO<BusinessTraditionChanceVO> getBusinessTraditionChanceVOPageResultVO(StopWatch stopWatch, Page<BusinessTraditionChance> businessTraditionChancesPage, List<BusinessTraditionChance> traditionChances, String token) {
        stopWatch.start("tradition-three");
        //需要数据处理，id转为文字
        List<BusinessTraditionChanceVO> chanceVOS = getBusinessTraditionChanceVOS(traditionChances, token);
        stopWatch.stop();
        log.info("传统耗时 {}", stopWatch.prettyPrint());
        PageResultVO<BusinessTraditionChanceVO> result = new PageResultVO<>();
        result.setRows(chanceVOS);
        result.setTotal(businessTraditionChancesPage.getTotalElements());
        return result;
    }

    private Specification<BusinessTraditionChance> getBusinessTraditionChanceSpecification(TraditionChanceCondition condition, List<Long> finalSiteIds) {
        return new Specification<BusinessTraditionChance>() {
                @Override
                public Predicate toPredicate(Root<BusinessTraditionChance> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                    List<Predicate> predicateList = Lists.newArrayList();
                    //系统来源
                    Optional.ofNullable(condition.getSystemFrom()).ifPresent(o -> predicateList.add(criteriaBuilder.equal(root.get("systemFrom").as(Integer.class), o)));
                    //项目
                    Optional.ofNullable(condition.getItemId()).ifPresent(o -> predicateList.add(criteriaBuilder.equal(root.get("itemId").as(Integer.class), o)));

                    //省id
                    Optional.ofNullable(condition.getProvinceId()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.equal(root.get("provinceId").as(String.class), o)));
                    //市id
                    Optional.ofNullable(condition.getCityId()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.equal(root.get("cityId").as(String.class), o)));
                    //运营专员--咨询师
                    if (Objects.nonNull(condition.getTeacherId())) {
                        predicateList.add(criteriaBuilder.equal(root.get("teacherId").as(Long.class), condition.getTeacherId()));
                    } else if (Objects.nonNull(condition.getOgId())) {
                        //查询当前销售组下的所有咨询师
                        teacherIdIn(root, predicateList, condition.getOgId(), criteriaBuilder,condition.getToken());

                    } else if (Objects.nonNull(condition.getOdId())) {
                        //查询当前销售部下的所有咨询师
                        teacherIdIn(root, predicateList, condition.getOdId(), criteriaBuilder,condition.getToken());

                    } else if (Objects.nonNull(condition.getWorkRoomId())) {
                        //未分配的情况下，没有咨询师。那么查询的时候。（咨询师id集合{根据组织架构查的，不是前端传的}  or  量子军团id）
                        Predicate quantumLegionId = criteriaBuilder.equal(root.get("quantumLegionId").as(Long.class), condition.getWorkRoomId());
                        predicateList.add(quantumLegionId);

                    } else if (Objects.nonNull(condition.getSkuId())) {
                        //未分配的情况下，没有咨询师。那么查询的时候。（咨询师id集合{根据组织架构查的，不是前端传的}  or  量子军团id）
                        List<DeptVO> deptlist = miniAdminService.getSonDeptList(condition.getSkuId());
                        CriteriaBuilder.In<Long> quantumLegionIdIn = null;
                        if (CollectionUtils.isNotEmpty(deptlist)) {
                            List<Long> deptIds = deptlist.stream().map(deptVO -> deptVO.getId()).collect(Collectors.toList());
                            quantumLegionIdIn = criteriaBuilder.in(root.get("quantumLegionId"));
                            Iterator<Long> it = deptIds.iterator();
                            while (it.hasNext()) {
                                quantumLegionIdIn.value(it.next());
                            }
                            predicateList.add(quantumLegionIdIn);
                        }

                    } else if (Objects.isNull(condition.getSkuId())) {

                        //跟进token查询量子军团id集合
                        List<DeptVO> deptlist = miniAdminService.getChildWorkRoomDeptList(condition.getToken());
                        CriteriaBuilder.In<Long> quantumLegionIdIn = null;
                        if (CollectionUtils.isNotEmpty(deptlist) && Objects.isNull(condition.getToufangStatus())) {
                            List<Long> deptIds = deptlist.stream().map(deptVO -> deptVO.getId()).collect(Collectors.toList());
                            quantumLegionIdIn = criteriaBuilder.in(root.get("quantumLegionId"));
                            Iterator<Long> iterator = deptIds.iterator();
                            while (iterator.hasNext()) {
                                quantumLegionIdIn.value(iterator.next());
                            }
                            predicateList.add(quantumLegionIdIn);
                        }else{
                            List<UserVO> userList = scopedOperationUserList(condition.getToken());
                            log.info("该账户下的权限范围内运营专员 {}", userList);
                            if(CollectionUtils.isNotEmpty(userList)){
                                //运营侧不查未分配的数据
                                CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("teacherId"));
                                Set<Long> userids = userList.stream().map(userVO -> userVO.getId()).collect(Collectors.toSet());
                                log.info("运营老师集合 {}", userids);
                                if(CollectionUtils.isNotEmpty(userids)){
                                    Iterator<Long> it = userids.iterator();
                                    while (it.hasNext()) {
                                        in.value(it.next());
                                    }
                                    predicateList.add(in);
                                }
                            }
                        }
                    }

                    //机会状态
                    if((Objects.nonNull(condition.getToufangStatus()) && condition.getToufangStatus().intValue() == 0) || (Objects.nonNull(condition.getExtendStatus()) && condition.getExtendStatus() == 3)){
                        //新机会=未跟进+无效跟进
                        //未跟进
                        Predicate chanceStatusUnfollow = criteriaBuilder.equal(root.get("chanceStatus").as(Integer.class), ChanceBaseInfoVO.ChanceStatus.unfollow.code);

                        //无效跟进
                        Predicate chanceStatusFollow = criteriaBuilder.equal(root.get("chanceStatus").as(Integer.class), ChanceBaseInfoVO.ChanceStatus.follow.code);
                        Predicate lastFollowUpTimeIsNotNull = criteriaBuilder.isNotNull(root.get("lastFollowUpTime").as(Date.class));
                        Predicate lastValidFollowUpTime = criteriaBuilder.isNull(root.get("lastValidFollowUpTime").as(Date.class));
                        Predicate and = criteriaBuilder.and(lastFollowUpTimeIsNotNull, lastValidFollowUpTime, chanceStatusFollow);
                        List<Predicate> predicateAnd = Lists.newArrayList();
                        predicateAnd.add(and);
                        Predicate p = criteriaBuilder.and(predicateAnd.toArray(new Predicate[predicateAnd.size()]));
                        predicateList.add(criteriaBuilder.or(chanceStatusUnfollow, p));
                    }else{
                        Optional.ofNullable(condition.getChanceStatus()).ifPresent(o -> predicateList.add(criteriaBuilder.equal(root.get("chanceStatus").as(Integer.class), o)));
                        //跟进中状态：0无效跟进，1有效跟进
                        Integer followUpStatus = condition.getFollowUpStatus();
                        if (Objects.nonNull(followUpStatus)) {
                            //无效跟进
                            if (followUpStatus.intValue() == TraditionChanceCondition.FollowUpEnum.INVALID.code.intValue()) {
                                predicateList.add(criteriaBuilder.isNotNull(root.get("lastFollowUpTime").as(Date.class)));
                                predicateList.add(criteriaBuilder.isNull(root.get("lastValidFollowUpTime").as(Date.class)));
                            }
                            //有效跟进
                            if (followUpStatus.intValue() == TraditionChanceCondition.FollowUpEnum.VALID.code.intValue()) {
                                predicateList.add(criteriaBuilder.isNotNull(root.get("lastValidFollowUpTime").as(Date.class)));
                            }
                        }
                    }


                    //投放人员（负责人）ID 投放渠道ID
                    if (CollectionUtils.isNotEmpty(finalSiteIds)) {
                        CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("miniSiteId"));
                        finalSiteIds.forEach(o -> in.value(o));
                        predicateList.add(in);
                    }

    //                Join<BusinessTraditionChance, BusinessChancePhoneRecord> phoneJoinRecord = root.join("phoneRecord", JoinType.LEFT);
    //                Join<BusinessTraditionChance, BusinessChanceWechatRecord> wechatJoinRecord = root.join("wechatRecord", JoinType.LEFT);
    //                //关联记录表，必须是今日数据
    //                String today = CalendarUtil.getShortDateString(new Date());
    //                predicateList.add(criteriaBuilder.greaterThanOrEqualTo(phoneJoinRecord.get("createTime").as(Date.class), CalendarUtil.parseDefaultDate( today+ " 00:00:00")));
    //                predicateList.add(criteriaBuilder.lessThanOrEqualTo(phoneJoinRecord.get("createTime").as(Date.class), CalendarUtil.parseDefaultDate(today + " 23:59:59")));
    //                predicateList.add(criteriaBuilder.greaterThanOrEqualTo(wechatJoinRecord.get("createTime").as(Date.class), CalendarUtil.parseDefaultDate( today+ " 00:00:00")));
    //                predicateList.add(criteriaBuilder.lessThanOrEqualTo(wechatJoinRecord.get("createTime").as(Date.class), CalendarUtil.parseDefaultDate(today + " 23:59:59")));


                    //今日拨打次数
                    String todayCallNum = condition.getTodayCallNum();
                    if (StringUtils.isNotEmpty(todayCallNum)) {
                        String[] split = todayCallNum.split("-");
                        predicateList.add(criteriaBuilder.between(root.get("todayCallNum").as(Integer.class), Integer.parseInt(split[0]), Integer.parseInt(split[1])));
                    }
                    //今日微信条数
                    String todayChatNum = condition.getTodayChatNum();
                    if (StringUtils.isNotEmpty(todayChatNum)) {
                        String[] split = todayChatNum.split("-");
                        predicateList.add(criteriaBuilder.between(root.get("todayChatNum").as(Integer.class), Integer.parseInt(split[0]), Integer.parseInt(split[1])));
                    }
                    //加微状态
                    if (Objects.nonNull(condition.getIsAdd())) {
                        predicateList.add(criteriaBuilder.equal(root.get("isAdd").as(Boolean.class), condition.getIsAdd()));
                    }


                    //机会信息 模糊搜索 综合搜索：可搜索机会ID/手机号/微信号/昵称
                    Optional.ofNullable(condition.getChanceInfo()).filter(s -> !s.isEmpty()).ifPresent(o -> {
                        boolean numeric = StringUtils.isNumeric(o);
                        Join<BusinessTraditionChance, BusinessChanceWechat> wechatJoin = root.join("wechatList", JoinType.LEFT);
                        if (numeric) {
                            Join<BusinessTraditionChance, BusinessChancePhone> phoneJoin = root.join("phoneList", JoinType.LEFT);
                            //机会id或手机号查询
                            Predicate phone = criteriaBuilder.equal(phoneJoin.get("phone").as(String.class), encryptField(o));
                            Predicate studentNickname = criteriaBuilder.like(root.get("studentNickname").as(String.class), "%" + o + "%");
                            if(Objects.nonNull(condition.getToufangStatus())){
                                Predicate id = criteriaBuilder.equal(root.get("id").as(Long.class),  o);
                                Predicate wechatNo = criteriaBuilder.equal(wechatJoin.get("wechatNo").as(String.class), o);

                                predicateList.add(criteriaBuilder.or(id, phone, wechatNo, studentNickname));
                            }else{
                                Predicate id = criteriaBuilder.like(root.get("id").as(String.class), "%" + o + "%");
                                Predicate wechatNo = criteriaBuilder.like(wechatJoin.get("wechatNo").as(String.class), "%" + o + "%");

                                predicateList.add(criteriaBuilder.or(id, phone, wechatNo, studentNickname));
                            }


                        } else {
                            Predicate studentNickname = criteriaBuilder.like(root.get("studentNickname").as(String.class), "%" + o + "%");
                            if(Objects.nonNull(condition.getToufangStatus())){
                                //微信号或昵称
                                Predicate wechatNo = criteriaBuilder.equal(wechatJoin.get("wechatNo").as(String.class),  o);
                                predicateList.add(criteriaBuilder.or(wechatNo, studentNickname));
                            }else{
                                //微信号或昵称
                                Predicate wechatNo = criteriaBuilder.like(wechatJoin.get("wechatNo").as(String.class), "%" + o + "%");
                                predicateList.add(criteriaBuilder.or(wechatNo, studentNickname));
                            }

                        }
                    });
                    //站点信息 模糊搜索 综合搜索：可搜索飞天站点/飞天站点名称
                    Optional.ofNullable(condition.getSiteInfo()).filter(s -> !s.isEmpty()).ifPresent(o -> {
                        //站点或站点名称

                        boolean numeric = StringUtils.isNumeric(o);
                        if (numeric) {
                            Predicate miniSiteId = criteriaBuilder.equal(root.get("miniSiteId").as(Long.class), o);
                            Predicate miniSiteName = criteriaBuilder.like(root.get("miniSiteName").as(String.class), "%" + o + "%");
                            predicateList.add(criteriaBuilder.or(miniSiteId, miniSiteName));
                        }else{
                            predicateList.add(criteriaBuilder.like(root.get("miniSiteName").as(String.class), "%" + o + "%"));
                        }
                    });
                    //时间筛选
                    List<ChanceTimeCondition> chanceTimes = condition.getChanceTimes();
                    if (CollectionUtils.isNotEmpty(chanceTimes)) {
                        chanceTimes.forEach(chanceTimeCondition -> {
                            int typeValue = chanceTimeCondition.getType().intValue();
                            if (typeValue == TraditionChanceCondition.ChanceTimeEnum.distribution.code) {

                                if(Objects.nonNull(chanceTimeCondition.getBeginTime()) && chanceTimeCondition.getBeginTime().length() > 10){
                                    predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("distributeTime").as(Date.class), CalendarUtil.parseDefaultDate(chanceTimeCondition.getBeginTime())));
                                }else{
                                    Optional.ofNullable(chanceTimeCondition.getBeginTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("distributeTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 00:00:00"))));
                                }

                                Optional.ofNullable(chanceTimeCondition.getEndTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get("distributeTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 23:59:59"))));
                            }
                            if (typeValue == TraditionChanceCondition.ChanceTimeEnum.create.code) {
                                Optional.ofNullable(chanceTimeCondition.getBeginTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 00:00:00"))));
                                Optional.ofNullable(chanceTimeCondition.getEndTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 23:59:59"))));
                            }
                            if (typeValue == TraditionChanceCondition.ChanceTimeEnum.lastFollowUp.code) {
                                Optional.ofNullable(chanceTimeCondition.getBeginTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("lastFollowUpTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 00:00:00"))));
                                Optional.ofNullable(chanceTimeCondition.getEndTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get("lastFollowUpTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 23:59:59"))));
                            }
                            if (typeValue == TraditionChanceCondition.ChanceTimeEnum.lastValidFollowUp.code) {
                                Optional.ofNullable(chanceTimeCondition.getBeginTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("lastValidFollowUpTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 00:00:00"))));
                                Optional.ofNullable(chanceTimeCondition.getEndTime()).filter(s -> !s.isEmpty()).ifPresent(o -> predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get("lastValidFollowUpTime").as(Date.class), CalendarUtil.parseDefaultDate(o + " 23:59:59"))));
                            }
                        });
                    }
                    criteriaQuery.groupBy(root.get("id").as(Long.class));
                    return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
                }
            };
    }

    private PageResultVO<BusinessTraditionChanceVO> getBusinessTraditionChanceVOPageResultVO() {
        PageResultVO<BusinessTraditionChanceVO> result = new PageResultVO<>();
        result.setRows(Collections.EMPTY_LIST);
        result.setTotal(0L);
        return result;
    }

    private void teacherIdIn(Root<BusinessTraditionChance> root, List<Predicate> predicateList, Long deptId, CriteriaBuilder criteriaBuilder,String token) {
        List<UserVO> userVOS = getUserVOS(deptId,token);
        if (CollectionUtils.isNotEmpty(userVOS)) {
            List<Long> usserIdList = userVOS.stream().map(userVO -> userVO.getId()).collect(Collectors.toList());
            CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("teacherId"));
            Iterator<Long> it = usserIdList.iterator();
            while (it.hasNext()) {
                in.value(it.next());
            }
            predicateList.add(in);
        }
    }

    private List<UserVO> getUserVOS(Long deptId, String token) {
        List<UserVO> businessResult = miniAdminService.operationUserFilter(token, Collections.singleton(deptId));
        return businessResult;
    }

    public List<BusinessTraditionChanceVO> getBusinessTraditionChanceVOS(List<BusinessTraditionChance> traditionChances, String token) {
        Set<Long> teacherIds = new HashSet<>();
        Set<Long> miniSiteId = new HashSet<>();
        Set<String> phone = new HashSet<>();
        traditionChances.forEach(businessTraditionChance -> {
            if(Objects.nonNull(businessTraditionChance.getTeacherId())){
                teacherIds.add(businessTraditionChance.getTeacherId());
            }
            miniSiteId.add(businessTraditionChance.getMiniSiteId());
        });

        List<BusinessTraditionChanceVO> chanceVOS = BusinessTraditionChanceVO.fromDO(traditionChances);
        List<UserVO> userVOS = miniAdminService.batchFindUserList(teacherIds);
        Map<Long, List<UserVO>> teacherMap = userVOS.stream().collect(Collectors.groupingBy(o -> o.getId()));

        // 根据站点查投放信息/渠道
        List<BusinessBaseInfo> baseInfoList = businessBaseInfoRepository.findAllByMiniLessonIdIn(miniSiteId);
        Map<Long, List<BusinessBaseInfo>> baseInfoMap = baseInfoList.stream().collect(Collectors.groupingBy(o -> o.getMiniLessonId()));


        List<BusinessItemInfo> itemInfos = getAllItemInfo();
        Map<Integer, List<BusinessItemInfo>> listMap = itemInfos.stream().collect(Collectors.groupingBy(o -> o.getId()));

//        Map<String, List<BusinessAliCallInfo>> finalMapPhone = mapPhone;
        chanceVOS.forEach(businessTraditionChanceVO -> {
            List<UserVO> userVOList = teacherMap.get(businessTraditionChanceVO.getTeacherId());
            Integer itemId = businessTraditionChanceVO.getItemId();
            if (Objects.nonNull(itemId)) {
                businessTraditionChanceVO.setItemName(listMap.get(itemId).get(0).getItemName());
            }
            Integer systemFrom = businessTraditionChanceVO.getSystemFrom();
            if (Objects.nonNull(systemFrom)) {
                businessTraditionChanceVO.setSystemFromDesc(ChanceBaseInfoVO.SystemFromEnum.getSystemFrom(systemFrom).desc);
            }
            if (CollectionUtils.isNotEmpty(userVOList)) {
                FullDeptVo fullDept = userVOList.get(0).getFullDept();
                //军团
                businessTraditionChanceVO.setSkuId(fullDept.getSkuId());
                businessTraditionChanceVO.setSkuName(fullDept.getSkuName());
                //量子军团
                businessTraditionChanceVO.setTeacherWorkRoomId(fullDept.getWorkRoomId());
                businessTraditionChanceVO.setTeacherWorkRoomName(fullDept.getWorkRoomName());
                //运营部门
                businessTraditionChanceVO.setOdId(fullDept.getOdId());
                businessTraditionChanceVO.setOdName(fullDept.getOdName());
                //运营组
                businessTraditionChanceVO.setOgId(fullDept.getOgId());
                businessTraditionChanceVO.setOgName(fullDept.getOgName());
            }
            List<BusinessBaseInfo> businessBaseInfos = baseInfoMap.get(businessTraditionChanceVO.getMiniSiteId());
            if (CollectionUtils.isNotEmpty(businessBaseInfos)) {
                BusinessBaseInfo baseInfo = businessBaseInfos.get(0);
                //投放人员
                businessTraditionChanceVO.setFzId(baseInfo.getFzId());
                businessTraditionChanceVO.setFzName(baseInfo.getFzName());
                //军团
                businessTraditionChanceVO.setSkuId(Long.parseLong(baseInfo.getArmyGroupId()));
                businessTraditionChanceVO.setSkuName(baseInfo.getArmyGroupName());

                //量子军团
                businessTraditionChanceVO.setTeacherWorkRoomId(Long.parseLong(baseInfo.getQuantumGroupId()));
                businessTraditionChanceVO.setTeacherWorkRoomName(baseInfo.getQuantumGroupName());

                //渠道
                businessTraditionChanceVO.setChannelCode(baseInfo.getChannelCode());
                businessTraditionChanceVO.setChannelId(baseInfo.getChannelId());
                businessTraditionChanceVO.setChannelName(baseInfo.getChannelName());
            }

            UserVO userVO = miniAdminService.getLoginUser(token);
            //非运营专员角色（运营管理层）：手机号和微信号均加密。前端展示和导出也加密
            //手机号加密规则：185****8072
            //微信加密规则：liu*****(除了前3位，都隐藏)

            final Date[] oldCreateTime = {new Date()};
            List<BusinessChancePhone> phoneList = businessTraditionChanceVO.getPhoneList();
            if (CollectionUtils.isNotEmpty(phoneList)) {
                phoneList.forEach(businessChancePhone -> {
                    String encryptPhone = businessChancePhone.getPhone();
                    String phoneReal = decryptField(encryptPhone);
                    businessChancePhone.setRealPhone(phoneReal);
                    businessChancePhone.setPhone(phoneReal.replace(phoneReal.substring(3, 7), "*****"));
                    if (userVO.isZhuanyuan()) {
                        businessChancePhone.setPhone(phoneReal);
                    }
                    businessChancePhone.setTimestamp(businessChancePhone.getCreateTime().getTime());
                    if(oldCreateTime[0].compareTo(businessChancePhone.getCreateTime()) > 0){
                        oldCreateTime[0] = businessChancePhone.getCreateTime();
                        businessTraditionChanceVO.setEnterType(businessChancePhone.getEnterType());
                    }
                    String onlineCard = businessChancePhone.getOnlineCard();
                    if(StringUtils.isNotEmpty(onlineCard)){
                        String content = RegexUtil.regexMobile(onlineCard);
                        businessChancePhone.setOnlineCard(content);
                    }
                });
                phoneList.sort((o1, o2) -> o2.getFrontDiaplay().compareTo(o1.getFrontDiaplay()));
            }

            List<BusinessChanceWechat> wechatList = businessTraditionChanceVO.getWechatList();
            if (CollectionUtils.isNotEmpty(wechatList)) {
                wechatList.forEach(businessChanceWechat -> {
                    StringBuffer wechatNo = new StringBuffer(businessChanceWechat.getWechatNo());
                    businessChanceWechat.setRealWechatNo(wechatNo.toString());
                    if (userVO.isZhuanyuan()) {
                        businessChanceWechat.setWechatNo(wechatNo.toString());
                    }else {
                        businessChanceWechat.setWechatNo(wechatNo.replace(3, wechatNo.length(), "****").toString());
                    }
                    businessChanceWechat.setTimestamp(businessChanceWechat.getCreateTime().getTime());
                    if(oldCreateTime[0].compareTo(businessChanceWechat.getCreateTime()) > 0){
                        oldCreateTime[0] = businessChanceWechat.getCreateTime();
                        businessTraditionChanceVO.setEnterType(businessChanceWechat.getEnterType());
                    }
                    String onlineCard = businessChanceWechat.getOnlineCard();
                    if(StringUtils.isNotEmpty(onlineCard)){
                        String content = RegexUtil.regexMobile(onlineCard);
                        businessChanceWechat.setOnlineCard(content);
                    }
                    businessChanceWechat.setIsAddDesc(getDesc(businessChanceWechat.getIsAdd()));
                });
                wechatList.sort((o1, o2) -> o2.getFrontDiaplay().compareTo(o1.getFrontDiaplay()));
            }
            businessTraditionChanceVO.setChanceStatusDesc(ChanceBaseInfoVO.ChanceStatus.getChanceStatus(businessTraditionChanceVO.getChanceStatus()).desc);
            businessTraditionChanceVO.setIntention(ChanceBaseInfoVO.IntentionEnum.getIntentionDesc(businessTraditionChanceVO.getIntentionCode()).desc);
            if(businessTraditionChanceVO.getChanceStatus().intValue() == ChanceBaseInfoCondition.ChanceStatusEnum.nodistribute.code){
                Date createTime = businessTraditionChanceVO.getCreateTime();
                Date today = CalendarUtil.parseShortDate(CalendarUtil.getShortDateString(new Date()));

                if(createTime.compareTo(today) > 0){
                    businessTraditionChanceVO.setHandDistribute(true);
                    businessTraditionChanceVO.setChanceStatusDesc(ChanceBaseInfoVO.ChanceStatus.distributing.desc);
                }else{
                    businessTraditionChanceVO.setHandDistribute(true);
                }
            }

            businessTraditionChanceVO.setIsAddDesc(getDesc(businessTraditionChanceVO.getIsAdd()));
            businessTraditionChanceVO.setIsCallDesc(getDesc(businessTraditionChanceVO.getIsCall()));

        });
        return chanceVOS;
    }

    private String getDesc(Boolean isBoolean){
        if(Objects.isNull(isBoolean)){
            return "无";
        }else if(isBoolean){
            return "是";
        }else{
            return "否";
        }
    }

    public BusinessTraditionChanceVO transSingleVO(BusinessTraditionChance businessTraditionChance, String token){
        return getBusinessTraditionChanceVOS(Collections.singletonList(businessTraditionChance), token).get(0);
    }


    //手动分配
    @Transactional(rollbackFor = Exception.class)
    public void handDistribute(BusinessTraditionChance traditionChanceDB, Long teacherId) {
        UserVO userSimpleInfo = miniAdminService.getUserSimpleInfo(teacherId);
        convertData(traditionChanceDB, userSimpleInfo, null);
    }


    //转归属
    @Transactional(rollbackFor = Exception.class)
    public void convertTeacher(BusinessTraditionChance traditionChanceDB, Long teacherId,String token,String condition) {

        String oldNickName = miniAdminService.getUserNickName(traditionChanceDB.getTeacherId());
        UserVO userSimpleInfo = miniAdminService.getUserSimpleInfo(teacherId);
        UserVO operationUserInfo = miniAdminService.getLoginUser(token);
        String newNickName = userSimpleInfo.getNickname();
        //先保存一份记录
        BusinessChanceConvertRecord businessChanceConvertRecord = BusinessChanceConvertRecord.builder().
                chanceId(traditionChanceDB.getId()).
                callNum(traditionChanceDB.getCallNum()).
                oldTeacherId(traditionChanceDB.getTeacherId()).
                oldTeacherName(oldNickName).
                newTeacherId(teacherId).
                newTeacherName(newNickName).
                operationId(operationUserInfo.getId()).
                operationName(operationUserInfo.getNickname()).
                searchParams(condition).
                build();
        businessChanceConvertRecordRepository.save(businessChanceConvertRecord);
        convertData(traditionChanceDB, userSimpleInfo, traditionChanceDB.getTeacherId());
    }

    public List<BusinessChanceConvertRecord> convertRecord(Long chanceId) {
        return businessChanceConvertRecordRepository.findAllByChanceIdOrderByCreateTimeDesc(chanceId);
    }

    private void convertData(BusinessTraditionChance traditionChanceDB, UserVO userSimpleInfo, Long oldTeacherId) {
        //修改联系方式中信息
        List<BusinessChancePhone> phoneList = traditionChanceDB.getPhoneList();
        if (CollectionUtils.isNotEmpty(phoneList)) {

            phoneList.forEach(businessChancePhone -> {
                businessChancePhone.setTeacherId(userSimpleInfo.getId());
                businessChancePhone.setCallNum(0);
            });
            businessChancePhoneRepository.save(phoneList);
        }
        List<BusinessChanceWechat> wechatList = traditionChanceDB.getWechatList();
        if (CollectionUtils.isNotEmpty(wechatList)) {
            wechatList.forEach(businessChanceWechat -> {
                businessChanceWechat.setChatNum(0);
                businessChanceWechat.setIsAdd(false);
                businessChanceWechat.setTeacherId(userSimpleInfo.getId());
            });
            businessChanceWechatRepository.save(wechatList);
        }
        List<BusinessChancePhoneRecord> phoneRecord = traditionChanceDB.getPhoneRecord();
        if (CollectionUtils.isNotEmpty(phoneRecord)) {
            phoneRecord.stream().
                    filter(businessChancePhoneRecord -> CalendarUtil.getShortDateString(businessChancePhoneRecord.getCreateTime()).equals(CalendarUtil.getShortDateString(new Date()))).
                    collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getPhone()))), ArrayList::new)).
                    forEach(businessChancePhoneRecord -> {
                BusinessChancePhoneRecord chancePhoneRecord = new BusinessChancePhoneRecord();
                copyNonNullProperties(businessChancePhoneRecord, chancePhoneRecord);
                chancePhoneRecord.setId(null);
                chancePhoneRecord.setTeacherId(userSimpleInfo.getId());
                chancePhoneRecord.setTodayCallNum(0);
                businessChancePhoneRecordRepository.save(chancePhoneRecord);
            });
        }
        List<BusinessChanceWechatRecord> wechatRecord = traditionChanceDB.getWechatRecord();
        if (CollectionUtils.isNotEmpty(wechatRecord)) {
            wechatRecord.stream().
                    filter(businessChanceWechatRecord -> CalendarUtil.getShortDateString(businessChanceWechatRecord.getCreateTime()).equals(CalendarUtil.getShortDateString(new Date()))).
                    collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getWechatNo()))), ArrayList::new)).
                    forEach(businessChanceWechatRecord -> {
                BusinessChanceWechatRecord chanceWechatRecord = new BusinessChanceWechatRecord();
                copyNonNullProperties(businessChanceWechatRecord, chanceWechatRecord);
                chanceWechatRecord.setId(null);
                chanceWechatRecord.setTeacherId(userSimpleInfo.getId());
                chanceWechatRecord.setTodayChatNum(0);
                businessChanceWechatRecordRepository.save(chanceWechatRecord);
            });
        }
        traditionChanceDB.setTeacherName(userSimpleInfo.getNickname());
        traditionChanceDB.setTeacherId(userSimpleInfo.getId());
        traditionChanceDB.setQuantumLegionId(userSimpleInfo.getFullDept().getWorkRoomId());
        //状态变更为未跟进
        traditionChanceDB.setChanceStatus(0);
        //分配时间
        traditionChanceDB.setDistributeTime(new Date());
        //反馈时间
        traditionChanceDB.setFeedbackTime(null);
        //末次跟进时间
        traditionChanceDB.setLastFollowUpTime(null);
        //末次有效跟进时间
        traditionChanceDB.setLastValidFollowUpTime(null);
        traditionChanceDB.setIsAdd(false);
        traditionChanceDB.setTodayChatNum(0);
        traditionChanceDB.setTodayCallNum(0);

        if(Objects.nonNull(oldTeacherId)){
            //转归属
            traditionChanceDB.setDistributeType(BusinessTraditionChanceVO.DistributeTypeEnum.convert.code);
        }else{
            //手动分配
            traditionChanceDB.setDistributeType(BusinessTraditionChanceVO.DistributeTypeEnum.handDistribute.code);
        }

        businessTraditionChanceRepository.save(traditionChanceDB);

        CompletableFuture.runAsync(() -> {
            if(Objects.nonNull(oldTeacherId)){
                ChanceFollowVO chanceFollowVO = ChanceFollowVO.
                        builder().
                        chanceId(traditionChanceDB.getId()).
                        eventTime(traditionChanceDB.getDistributeTime()).
                        eventType(ChanceFollowEventType.chance_transfer_sub).
                        teacherId(oldTeacherId).
                        build();
                sendMsg2RabbitMQService.sendMsg(chanceFollowVO);
            }
            ChanceFollowVO chanceFollowVO = ChanceFollowVO.
                    builder().
                    chanceId(traditionChanceDB.getId()).
                    eventTime(traditionChanceDB.getDistributeTime()).
                    eventType(oldTeacherId == null? ChanceFollowEventType.chance_allocate_operate : ChanceFollowEventType.chance_transfer).
                    teacherId(userSimpleInfo.getId()).
                    dataAttach(oldTeacherId == null? null : oldTeacherId.toString()).
                    build();
            sendMsg2RabbitMQService.sendMsg(chanceFollowVO);
        });
    }

    //添加微信号
    @Transactional(rollbackFor = Exception.class)
    public BusinessChanceWechat addWechatNO(BusinessTraditionChance traditionChanceDB, String wechatNo) {
        BusinessChanceWechat chanceWechat = new BusinessChanceWechat();
        chanceWechat.setTeacherId(traditionChanceDB.getTeacherId());
        chanceWechat.setWechatNo(wechatNo);
        chanceWechat.setChanceId(traditionChanceDB.getId());
        chanceWechat.setEnterType(2);
        chanceWechat.setChatNum(0);
        businessChanceWechatRepository.save(chanceWechat);
        //操作记录
        BusinessWechatOperateRecord businessWechatOperateRecord = BusinessWechatOperateRecord.
                builder().
                wechatNo(wechatNo).
                event("点击添加微信号【" + wechatNo + "】").
                build();
        businessWechatOperateRecordRepository.save(businessWechatOperateRecord);
        //自动验证是否好友关系
        BusinessChanceWechat wechatUserInfoVO = getRelation(traditionChanceDB, chanceWechat, wechatNo);
        CompletableFuture.runAsync(() -> {
            frontDiaplayWechatNo(chanceWechat);
        });
        return wechatUserInfoVO;
    }


    public BusinessChanceWechat getRelation(BusinessTraditionChance traditionChanceDB, BusinessChanceWechat chanceWechat, String wechatNo) {
        //调用外部接口，返回学员微信信息，如果不是好友，获取不到
        BusinessResult<WechatUserInfoVO> businessResult = wehubSocketReceiverClient.infoUser(reqSign, traditionChanceDB.getTeacherId(), wechatNo);
        log.info("校验好友关系，返回 {}", businessResult);
        WechatUserInfoVO data = businessResult.getData();
        if (Objects.nonNull(data) && StringUtils.isNotBlank(data.getWxId())) {
            //更新微信资料以及加微状态
            chanceWechat.setIsAdd(true);
            chanceWechat.setCountry(data.getCountry());
            chanceWechat.setProvince(data.getProvince());
            chanceWechat.setCity(data.getCity());
            //备注：20-10-19-ID69636990 （分配时间 +机会ID
            chanceWechat.setRemark(CalendarUtil.getShortDateString(traditionChanceDB.getDistributeTime())+"-ID"+traditionChanceDB.getId());
            chanceWechat.setSex(data.getSex());
            chanceWechat.setHeadImg(data.getHeadImg());
            chanceWechat.setNickName(data.getNickName());
            chanceWechat.setWxId(data.getWxId());

            businessChanceWechatRepository.save(chanceWechat);
            if (Objects.isNull(traditionChanceDB.getIsAdd()) || !traditionChanceDB.getIsAdd()) {
                traditionChanceDB.setIsAdd(true);
                Date date = new Date();
                //机会状态
                if(traditionChanceDB.getChanceStatus().intValue() == ChanceBaseInfoCondition.ChanceStatusEnum.unfollow.code){
                    traditionChanceDB.setChanceStatus(ChanceBaseInfoCondition.ChanceStatusEnum.follow.code);
                }
                //反馈时间
                if(Objects.isNull(traditionChanceDB.getFeedbackTime())){
                    traditionChanceDB.setFeedbackTime(date);
                }
                //末次跟进时间
                traditionChanceDB.setLastFollowUpTime(date);
                //末次有效跟进时间
                traditionChanceDB.setLastValidFollowUpTime(date);

                businessTraditionChanceRepository.save(traditionChanceDB);
            }
            //操作记录
            CompletableFuture.runAsync(() -> {
                BusinessWechatOperateRecord businessWechatOperateRecord = BusinessWechatOperateRecord.
                        builder().
                        wechatNo(wechatNo).
                        event("点击检测，“已加成，wehub检测成功”").
                        build();
                businessWechatOperateRecordRepository.save(businessWechatOperateRecord);
                //wechat_apply_pass ,微信加好友-通过好友关系验证
                ChanceFollowVO callConnect = ChanceFollowVO.
                        builder().
                        chanceId(traditionChanceDB.getId()).
                        eventTime(chanceWechat.getUpdateTime()).
                        eventType(ChanceFollowEventType.wechat_apply_pass).
                        teacherId(traditionChanceDB.getTeacherId()).
                        build();
                sendMsg2RabbitMQService.sendMsg(callConnect);
            });
        }else{
            //操作记录
            CompletableFuture.runAsync(() -> {
                BusinessWechatOperateRecord businessWechatOperateRecord = BusinessWechatOperateRecord.
                        builder().
                        wechatNo(wechatNo).
                        event("点击检测，“未加成，wehub未检测到好友”").
                        build();
                businessWechatOperateRecordRepository.save(businessWechatOperateRecord);

                //wechat_apply_failed ,微信加好友-不是好友关系
                ChanceFollowVO callConnect = ChanceFollowVO.
                        builder().
                        chanceId(traditionChanceDB.getId()).
                        eventTime(new Date()).
                        eventType(ChanceFollowEventType.wechat_apply_failed).
                        teacherId(traditionChanceDB.getTeacherId()).
                        build();
                sendMsg2RabbitMQService.sendMsg(callConnect);
            });
        }
        return chanceWechat;
    }

    //更新今日微信条数
    @Transactional(rollbackFor = Exception.class)
    public void updateWechatRecord(String wxId) {
        BusinessChanceWechat chanceWechat = businessChanceWechatRepository.findByWxId(wxId);
        if (Objects.nonNull(chanceWechat)) {
            chanceWechat.setChatNum(chanceWechat.getChatNum() + 1);
            chanceWechat.setIsAdd(true);
            businessChanceWechatRepository.save(chanceWechat);
            BusinessChanceWechatRecord todayWechatRecord = businessChanceWechatRecordRepository.findTodayByWechatNo(chanceWechat.getWechatNo());
            if (Objects.isNull(todayWechatRecord)) {
                //插入记录
                todayWechatRecord = new BusinessChanceWechatRecord();
                todayWechatRecord.setTeacherId(chanceWechat.getTeacherId());
                todayWechatRecord.setTodayChatNum(1);
                todayWechatRecord.setChanceId(chanceWechat.getChanceId());
                todayWechatRecord.setWechatNo(chanceWechat.getWechatNo());
            } else {
                todayWechatRecord.setTodayChatNum(todayWechatRecord.getTodayChatNum() + 1);
            }
            businessChanceWechatRecordRepository.save(todayWechatRecord);

            Date date = new Date();
            //更新机会表的跟进状态，时间等
            BusinessTraditionChance traditionChance = businessTraditionChanceRepository.findOne(chanceWechat.getChanceId());
            if(traditionChance == null)return;
            Integer chanceStatus = traditionChance.getChanceStatus();
            if (chanceStatus.intValue() == ChanceBaseInfoCondition.ChanceStatusEnum.unfollow.code.intValue()) {
                //机会状态
                traditionChance.setChanceStatus(ChanceBaseInfoCondition.ChanceStatusEnum.follow.code);
                //反馈时间(机会状态从未跟进变为跟进中的的时间)
                traditionChance.setFeedbackTime(date);
            }
            //加微状态
            if (!traditionChance.getIsAdd()) {
                traditionChance.setIsAdd(true);
            }
            traditionChance.setTodayChatNum(traditionChance.getTodayChatNum() + 1);
            //末次跟进时间
            traditionChance.setLastFollowUpTime(date);
            //有效跟进
            traditionChance.setLastValidFollowUpTime(date);
            businessTraditionChanceRepository.save(traditionChance);
            CompletableFuture.runAsync(() -> {
                //wechat_from_teacher ,发送消息-咨询师发送
                ChanceFollowVO callConnect = ChanceFollowVO.
                        builder().
                        chanceId(traditionChance.getId()).
                        eventTime(new Date()).
                        eventType(ChanceFollowEventType.wechat_from_teacher).
                        teacherId(traditionChance.getTeacherId()).
                        build();
                sendMsg2RabbitMQService.sendMsg(callConnect);
            });

        } else {
            log.info("{}这个微信id在机会里不存在", wxId);
        }
    }

    //添加手机号
    @Transactional(rollbackFor = Exception.class)
    public BusinessChancePhone addPhone(BusinessTraditionChance traditionChanceDB, Long phone) {
        BusinessChancePhone chancePhone = new BusinessChancePhone();
        chancePhone.setTeacherId(traditionChanceDB.getTeacherId());
        chancePhone.setPhone(this.encryptField(phone + ""));
        chancePhone.setChanceId(traditionChanceDB.getId());
        //2手动录入
        chancePhone.setEnterType(2);
        chancePhone.setCallNum(0);
        //手机号归属
        BusinessResult<PhoneInfoVO> businessResult = assignClient.mobileLocation(reqSign, phone + "");
        PhoneInfoVO phoneInfoVO = businessResult.getData();
        if (Objects.nonNull(phoneInfoVO)) {
            chancePhone.setProvince(phoneInfoVO.getProvince());
            chancePhone.setCity(phoneInfoVO.getCity());
            chancePhone.setCompany(phoneInfoVO.getCompany());
        }
        BusinessChancePhone businessChancePhone = businessChancePhoneRepository.save(chancePhone);
        CompletableFuture.runAsync(() -> {
            frontDiaplayPhone(businessChancePhone);
        });

        return businessChancePhone;
    }

    //更新今日拨打次数，以及跟进时间（有效/无效）
    public void updatePhoneRecord(BusinessChancePhone chancePhone, BusinessCallInfoVO callInfoVO) {
        BusinessChancePhoneRecord phoneRecord = businessChancePhoneRecordRepository.findTodayByPhone(chancePhone.getPhone());
        if (Objects.isNull(phoneRecord)) {
            //插入记录
            phoneRecord = new BusinessChancePhoneRecord();
            phoneRecord.setTodayCallNum(1);
            phoneRecord.setTeacherId(chancePhone.getTeacherId());
            phoneRecord.setChanceId(chancePhone.getChanceId());
            phoneRecord.setPhone(chancePhone.getPhone());

        } else {
            //更新记录
            phoneRecord.setTodayCallNum(phoneRecord.getTodayCallNum() + 1);
        }
        //记录表
        businessChancePhoneRecordRepository.save(phoneRecord);
        //联系方式表，总拨打次数加1
        chancePhone.setCallNum(chancePhone.getCallNum()==null? 1 : chancePhone.getCallNum()+ 1);
        businessChancePhoneRepository.save(chancePhone);

        Date date = new Date();
        //更新机会表的跟进状态，时间等
        BusinessTraditionChance traditionChance = businessTraditionChanceRepository.findOne(chancePhone.getChanceId());
        Integer chanceStatus = traditionChance.getChanceStatus();
        if (chanceStatus.intValue() == ChanceBaseInfoCondition.ChanceStatusEnum.unfollow.code.intValue()) {
            //机会状态
            traditionChance.setChanceStatus(ChanceBaseInfoCondition.ChanceStatusEnum.follow.code);
            //反馈时间(机会状态从未跟进变为跟进中的的时间)
            traditionChance.setFeedbackTime(date);
        }
        //拨打次数
        traditionChance.setCallNum(traditionChance.getCallNum() == null ? 1 : (traditionChance.getCallNum() + 1));
        traditionChance.setTodayCallNum(traditionChance.getTodayCallNum() == null ? 1 : (traditionChance.getTodayCallNum() + 1));
        //末次跟进时间
        traditionChance.setLastFollowUpTime(date);

        //接通且通话时长大于等于20s，为有效跟进
        if (callInfoVO.getAnswerStatus().intValue() == BusinessCallInfoVO.AnswerStatusEnum.connected.code.intValue() && callInfoVO.getDuration() >= 20) {
            traditionChance.setLastValidFollowUpTime(date);
        }
        businessTraditionChanceRepository.save(traditionChance);

        //异步存储，祥超需要统计使用
        CompletableFuture.runAsync(() -> {
//            BusinessChanceCallRecord businessChanceCallRecord = new BusinessChanceCallRecord();
//            copyNonNullProperties(callInfoVO, businessChanceCallRecord);
//            businessChanceCallRecord.setChanceId(traditionChance.getId());
//            businessChanceCallRecordRepository.save(businessChanceCallRecord);
            CompletableFuture.runAsync(() -> {
                //call_start ,拨打电话时间(记录创建时间）
                ChanceFollowVO callStart = ChanceFollowVO.
                        builder().
                        chanceId(traditionChance.getId()).
                        eventTime(callInfoVO.getCreateTime()).
                        eventType(ChanceFollowEventType.call_start).
                        teacherId(traditionChance.getTeacherId()).
                        build();
                sendMsg2RabbitMQService.sendMsg(callStart);
                if (callInfoVO.getAnswerStatus().intValue() == BusinessCallInfoVO.AnswerStatusEnum.connected.code.intValue()){
                    //call_connect, 接通时间
                    ChanceFollowVO callConnect = ChanceFollowVO.
                            builder().
                            chanceId(traditionChance.getId()).
                            eventTime(CalendarUtil.parseDefaultDate(callInfoVO.getStartTime())).
                            eventType(ChanceFollowEventType.call_connect).
                            teacherId(traditionChance.getTeacherId()).
                            build();
                    sendMsg2RabbitMQService.sendMsg(callConnect);
                    // call_end ,挂断时间（时长放在dataAttach中）
                    ChanceFollowVO callEnd = ChanceFollowVO.
                            builder().
                            chanceId(traditionChance.getId()).
                            eventTime(CalendarUtil.parseDefaultDate(callInfoVO.getEndTime())).
                            eventType(ChanceFollowEventType.call_end).
                            teacherId(traditionChance.getTeacherId()).
                            dataAttach(callInfoVO.getDuration().toString()).
                            build();
                    sendMsg2RabbitMQService.sendMsg(callEnd);
                }else{
                    //call_missed,未接通（时间可以随意）
                    ChanceFollowVO callMissed = ChanceFollowVO.
                            builder().
                            chanceId(traditionChance.getId()).
                            eventTime(callInfoVO.getUpdateTime()).
                            eventType(ChanceFollowEventType.call_missed).
                            teacherId(traditionChance.getTeacherId()).
                            build();
                    sendMsg2RabbitMQService.sendMsg(callMissed);
                }

            });
        });
    }

    public void updateChanceStatus(Long chanceId, Integer status){
        if(ChanceBaseInfoVO.ChanceStatus.getChanceStatus(status) == null){
            throw new IllegalArgumentException("无效的状态值");
        }

        BusinessTraditionChance traditionChanceDB = this.findOne(chanceId);
        if(Objects.isNull(traditionChanceDB)){
            throw new BusinessException("根据id查询不到当前数据");
        }
        traditionChanceDB.setChanceStatus(status);
        this.save(traditionChanceDB);
        log.info("更新机会状态 {}", traditionChanceDB);
    }

    public List<BusinessWechatOperateRecord> addWechatRecord(String wechatNo) {
        return businessWechatOperateRecordRepository.findAllByWechatNoOrderByCreateTimeDesc(wechatNo);
    }

    public BusinessChanceWechat wechatInfo(String wechatNo) {
        return businessChanceWechatRepository.findByWechatNo(wechatNo);
    }


    public BusinessTraditionChance findOne(Long id) {
        return businessTraditionChanceRepository.findOne(id);
    }

    public List<BusinessTraditionChance> findByIdIn(List<Long> ids) {
        return businessTraditionChanceRepository.findAllByIdIn(ids);
    }

    public BusinessTraditionChance save(BusinessTraditionChance traditionChanceDB) {
        return businessTraditionChanceRepository.save(traditionChanceDB);
    }

    public BusinessChancePhone findPhone(String phone) {
        return businessChancePhoneRepository.findByPhone(phone);
    }

    public BusinessChanceWechat findWechatNo(String wechatNo) {
        return businessChanceWechatRepository.findByWechatNo(wechatNo);
    }

    @Transactional(rollbackFor = Exception.class)
    public void frontDiaplayPhone(BusinessChancePhone businessChancePhone){
        businessChancePhone.setFrontDiaplay(true);
        List<BusinessChancePhone> chancePhones = businessChancePhoneRepository.findByChanceId(businessChancePhone.getChanceId());
        if(chancePhones.size() == 1){
            businessChancePhoneRepository.save(businessChancePhone);
        }else{
            List<BusinessChancePhone> collect = chancePhones.stream().filter(businessChancePhone1 -> !businessChancePhone1.getPhone().equals(businessChancePhone.getPhone())).map(chancePhone -> {
                chancePhone.setFrontDiaplay(false);
                return chancePhone;
            }).collect(Collectors.toList());
            collect.add(businessChancePhone);
            businessChancePhoneRepository.save(collect);
        }
    }
    public void frontDiaplayWechatNo(BusinessChanceWechat businessChanceWechat){
        businessChanceWechat.setFrontDiaplay(true);
        List<BusinessChanceWechat> chanceWechats = businessChanceWechatRepository.findByChanceId(businessChanceWechat.getChanceId());
        if(chanceWechats.size() == 1){
            businessChanceWechatRepository.save(businessChanceWechat);
        }else{
            List<BusinessChanceWechat> collect = chanceWechats.stream().filter(businessChanceWechat1 -> !businessChanceWechat1.getWechatNo().equals(businessChanceWechat.getWechatNo())).map(businessChanceWechat1 -> {
                businessChanceWechat1.setFrontDiaplay(false);
                return businessChanceWechat1;
            }).collect(Collectors.toList());
            collect.add(businessChanceWechat);
            businessChanceWechatRepository.save(collect);
        }
    }

    public String encryptPhone(String field) {
        //加密
        return encryptField(field);
    }

    public String decryptPhone(String field) {
        //解密
        return decryptField(field);
    }
}
